import { ConsoleLogger, ConsoleLoggerOptions, Injectable, LogLevel } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { Config, loggerConfig } from "src/config/config.interface";
import { createLogger, format, transports, type Logger as WinstonLogger } from "winston";
import 'winston-daily-rotate-file';


export enum LogLevels {
    ERROR = 'error',
    WARN = 'warn',
    INFO = 'info',
    HTTP = 'http',
    VERBOSE = 'verbose',
    DEBUG = 'debug',
    silly = 'silly',
}

@Injectable()
export class LoggerService extends ConsoleLogger { 
    private winstonLogger: WinstonLogger;
    constructor(context: string, options: ConsoleLoggerOptions, private configService: ConfigService<Config>) {
        super(context, options);
        this.initWinston();
    }

    // 设置日志级别
    protected get level(): LogLevel {
        return this.configService.get<loggerConfig>('logger')?.level as LogLevel;
    }

    protected get maxFiles(): number {
        return this.configService.get<loggerConfig>('logger')?.maxFiles as number;
    }


    protected initWinston(): void {
        this.winstonLogger = createLogger({
            level: this.level,
            format: format.combine(
                format.timestamp(),
                format.errors({ stack: true }),
                format.splat(),
                format.json(),
            ),
            defaultMeta: { service: this.context },
            transports: [
                //
                // - Write to all logs with level `info` and below to `combined.log`
                // - Write all logs error (and below) to `error.log`.
                //
                new transports.DailyRotateFile({
                    filename: 'logs/app.%DATE%.log', 
                    datePattern: 'YYYY-MM-DD', 
                    zippedArchive: true, 
                    maxSize: '20m', 
                    format: format.combine(format.timestamp(), format.json()),
                    maxFiles: this.maxFiles, 
                    level: this.level,
                    auditFile: 'logs/.audit/app.json',
                }),
                new transports.DailyRotateFile({
                    filename: 'logs/app-error.%DATE%.log', 
                    datePattern: 'YYYY-MM-DD', 
                    zippedArchive: true, 
                    maxSize: '20m', 
                    format: format.combine(format.timestamp(), format.json()),
                    maxFiles: this.maxFiles, 
                    level: LogLevels.ERROR,
                    auditFile: 'logs/.audit/app-error.json',
                }),
            ],
        });
    }

    // 重写log方法
    log(message: any, context?: string): void {
        super.log(message, context);
        this.winstonLogger.info(message);
    }

    // 重写error方法
    error(message: any, trace?: string, context?: string): void {
        super.error(message, trace, context);
        this.winstonLogger.error(message);
    }

    // 重写warn方法
    warn(message: any, context?: string): void {
        super.warn(message, context);
        this.winstonLogger.warn
    }

    // 重写warn方法
    verbose(message: unknown, context?: unknown,): void {
        super.verbose(message, context);
        this.winstonLogger.verbose(message);
    }
}